package alternativa {

	import alternativa.engine3d.loaders.ParserA3D;
	import alternativa.engine3d.materials.StandardMaterial;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.objects.Mesh;
	import alternativa.engine3d.resources.ATFTextureResource;

	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;


	public class AppearanceResources extends EventDispatcher {
		static public var resources:Object = new Object();
		private var resourceNames:Vector.<String> = new Vector.<String>();
		private var loadList:Vector.<String> = new Vector.<String>();
		private var data:Vector.<ByteArray> = new Vector.<ByteArray>();
		private var loader:URLLoader;
		private var index:uint;
		private var onLoadComplete:Function;
		private var path:String;
		private var parser:ParserA3D = new ParserA3D();
		private var resourceClasses:Vector.<Class> = new Vector.<Class>();
		private var event:ProgressEvent = new ProgressEvent(ProgressEvent.PROGRESS);

		public function AppearanceResources(path:String) {
			this.path = path;
		}

		protected function initResourcesList():void {
			resourceNames.length = 0;
			loadList.length = 0;
			addResource("arena");
			addResource("box");
			addResource("cannon");
			addResource("cannon_basement");
			addMesh("cone");
			addTextureMaterial("cone");
			addResource("cylinder");
			addResource("sphere", "cannonball");
			addTextureMaterial("sphere_LightBall");
			addResource("table_leg");
			addResource("table_top");
			addResource("target");
		}

		public function addMesh(name:String):void {
			resourceNames.push(name);
			loadList.push("Object_" + name + ".a3d");
			resourceClasses.push(Mesh);
		}

		public function addResource(name:String, suffix:String = null):void {

			addMesh(name);
			var fullname:String;
			if (suffix) {
				fullname = name + "_" + suffix;
			} else {
				fullname = name;
			}
			resourceNames.push(fullname + "_material");
			loadList.push("Object_" + fullname + "_Diffuse.atf");
			loadList.push("Object_" + fullname + "_Normal.atf");
			resourceClasses.push(StandardMaterial);
		}

		public function addTextureMaterial(name:String):void {
			resourceClasses.push(TextureMaterial);
			resourceNames.push(name + "_material");
			loadList.push("Object_" + name + "_Diffuse.atf");
		}

		public function loadResources(onLoadComplete:Function):void {
			this.onLoadComplete = onLoadComplete;
			initResourcesList();
			event.bytesTotal = loadList.length;
			loadNext(null);
		}

		public function loadNext(event:Event):void {
			if (event != null) {
				data.push(event.target.data);
				this.event.bytesLoaded = index;
				this.dispatchEvent(this.event);
			}
			if (index == loadList.length) {
				createResources();
				onLoadComplete();
				return;
			}
			loader = new URLLoader();
			loader.dataFormat = URLLoaderDataFormat.BINARY;
			loader.addEventListener(Event.COMPLETE, loadNext);
			var name:String = loadList[index];
			++index;
			loader.load(new URLRequest(path + name));
		}

		public function createResources():void {
			var ir:int,  nr:int = resourceNames.length, ic:int, j:int;
			for (ir = 0,ic = 0; ir < nr; ++ir) {
				switch (resourceClasses[ir]) {
					case Mesh:
					{
						parser.parse(data[ic]);
						var mesh:Mesh;
						for each (var obj:Object in parser.objects) {
							if (obj is Mesh) {
								mesh = obj as Mesh;
								break;
							}
						}
						resources[resourceNames[ir]] = mesh;
						ic++;
						break;
					}
					case StandardMaterial:
					{
						resources[resourceNames[ir]] = new StandardMaterial(new ATFTextureResource(data[ic]), new ATFTextureResource(data[ic + 1]));
						ic += 2;
						break;
					}
					case TextureMaterial:
					{
						resources[resourceNames[ir]] = new TextureMaterial(new ATFTextureResource(data[ic]));
						ic++;
						break;
					}
				}
			}
		}
	}
}
